package com.g8.pethospitallearnbackend.service.impls;

import com.g8.pethospitallearnbackend.entity.*;
import com.g8.pethospitallearnbackend.exception.CustomException;
import com.g8.pethospitallearnbackend.mapper.*;
import com.g8.pethospitallearnbackend.service.CaseService;
import com.g8.pethospitallearnbackend.utils.responseUtil.ResponseStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.event.MouseListener;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;

import java.util.List;
import java.util.Objects;

import static com.g8.pethospitallearnbackend.utils.NewIdGenerateUtil.getNumber;
import static com.g8.pethospitallearnbackend.utils.StringUtil.*;
import static com.g8.pethospitallearnbackend.utils.ValidateUtil.isDate;

@Slf4j
@Service
public class CaseServiceImpl implements CaseService {
    @Autowired
    private CaseMapper caseMapper;
    @Autowired
    private CasefieldsMapper casefieldsMapper;
    @Autowired
    private DiseaseMapper diseaseMapper;
    @Autowired
    private LabMapper labMapper;
    @Autowired
    private MedicineMapper medicineMapper;
    @Override
    public List<CaseIntro> getCaseIntroByDiseaseId(String diseaseId) {
        List<CaseIntro> caseIntros=caseMapper.selectIntros(diseaseId);
        return caseIntros;
    }

    /**
     * 主要工作是把中英文的模块名字匹配起来，然后通过英文字段名查找该caseId对应对象的属性
     * @param caseId
     * @param modules
     * @return
     */
    @Override
    public List<ModuleInfo> getModuleInfoToCaseId(String caseId, String modules) {
        //先通过caseId查询到对应的病例数据（所有字段的）
        Case specificCase=caseMapper.selectACaseById(caseId);
        if(specificCase==null){
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,"不存在该caseId");
        }
        //所有字段的中英文对应
        List<Casefields> allCaseFields=casefieldsMapper.selectAll();
        //返回数据moduleinfo的列表，类似于一个个小卡片，有模块名，英文名，值
        List<ModuleInfo> moduleInfos=new ArrayList<>();
        //入参modules处理，用|分割
        String[] moduleNames=modules.replace(" ","").split("&");//|是正则表达式中的字符，所以要转义
        //遍历modules，该模块下要展示的病例字段
        for(String value:moduleNames){
            String moduleChName=null;
            //通过英文名找中文名
            boolean isExist=false;//判断是否有没找到对应值的英文字段
            for(Casefields field:allCaseFields){
                if(Objects.equals(field.getEnAttr(), value)){
                    moduleChName=field.getChAttr();
                    isExist=true;
                    break;
                }
            }
            if(!isExist) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,"请求的字段不存在");

            //下划线命名转驼峰，因为case中的属性名称是驼峰命名，数据库中字段名（英文）是下划线
            String camelValue=convertToCamelCase(value);
            //用了java中的映射，来动态获取对象的某个属性值
            Object moduleValue = specificCase.getPropertyValue(camelValue);
            //统一返回的都是字符串，因为moduleinfo定义的属性都是字符串形式
            String moduleValueStr=null;
            //发现问题：case中不是所有字段都是string，有一个date需要额外处理一下，不然date不能直接强制转string，date.toString返回的形式是"Wed Mar 30 14:25:09 GMT 2024"，不符合要求，所以用util中的dateToString
            if(moduleValue instanceof Date) moduleValueStr=dateToString((Date) moduleValue);
            else moduleValueStr=(String) moduleValue;//不是date可以直接强制转换一下从object到string
            //搜集完数据了，构造moduleinfo
            ModuleInfo moduleInfo=new ModuleInfo(value,moduleChName, moduleValueStr);
            //添加到list中，返回
            moduleInfos.add(moduleInfo);
        }

        return moduleInfos;
    }

    @Override
    public List<Case> getAllCases() {
        //把disease, case_check, case_medicine全部对应到中文
        List<Case> selected=caseMapper.selectAllCases();
        for(Case aCase:selected){
            boolean first;
            //case_diseases
            String diseaseIds=aCase.getCaseDiseases();
            if(diseaseIds!=null){
                String[] diseaseIdArray=diseaseIds.replace(" ","").split("\\|");
                StringBuffer diseaseNames=new StringBuffer();
                first=true;
                for(String disease:diseaseIdArray){
                    String diseaseName=diseaseMapper.selectADiseaseById(disease).getDiseaseName();
                    if(first){
                        diseaseNames.append(diseaseName);
                        first=false;
                    }
                    else{
                        diseaseNames.append("|").append(diseaseName);
                    }
                }
                aCase.setCaseDiseases(diseaseNames.toString());
            }
            else aCase.setCaseDiseases("无");


            //case_check
            String labIds=aCase.getCaseCheck();
            if(labIds!=null){
                String[] labIdArray=labIds.replace(" ","").split("\\|");
                StringBuffer labNames=new StringBuffer();
                first=true;
                for(String lab:labIdArray){
                    String labName=labMapper.selectLabById(lab).getLabName();
                    if(first){
                        labNames.append(labName);
                        first=false;
                    }
                    else{
                        labNames.append("|").append(labName);
                    }

                }
                aCase.setCaseCheck(labNames.toString());
            }
            else aCase.setCaseCheck("无");


            //case_medicine
            String medIds=aCase.getCaseMedicine();
            if(medIds!=null){
                String[] medIdArray=medIds.replace(" ","").split("\\|");
                StringBuffer medNames=new StringBuffer();
                first=true;
                for(String med:medIdArray){
                    String medName=medicineMapper.selectMedicineById(med).getMedicineName();
                    if(first){
                        medNames.append(medName);
                        first=false;
                    }
                    else {
                        medNames.append("|").append(medName);
                    }

                }
                aCase.setCaseMedicine(medNames.toString());
            }
            else aCase.setCaseMedicine("无");

        }
        return selected;
    }

    /**
     * 修改病例信息，前端传回来的caseinfo中caseTime是string，但是实体类里面的case里是sql.date，
     * 所以先用中间的CaseReceived过度一下，把这个字段转换完后再重新构造case。
     * 还要把caseReceived病例中的文字对应到id插入
     * 由于病例列表中预留字段，所以前端返回的数据先要验证是否都是“真实的”的字段，不能是未启用的预留字段；
     * 且要保证字段的完整性，即所有已使用的字段必须传值。
     * @param caseId
     * @param caseinfo
     * @return
     */
    @Override
    public Case modifyACase(String caseId, CaseReceived caseinfo) {
        if(caseMapper.selectACaseById(caseId)==null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,"未查询到"+caseId);
        //先验证合法性，必须出现所有已使用的字段，没使用的必须为null
        if(validateFields(caseinfo)){
            // 将时间字符串转换为 Date 类型,还有一些名称转id
            Date caseTime=validateDateAndToSQLDate(caseinfo.getCaseTime());
            String caseDiseases=diseaseNamesToDiseaseIds(caseinfo.getCaseDiseases());
            String caseCheck=labNamesToLabIds(caseinfo.getCaseCheck());
            String caseMedicines=medicineNamesToMedicineIds(caseinfo.getCaseMedicine());

            //构造case，便于update
            Case convertToCase=new Case(
                    caseId,
                    caseDiseases,
                    caseTime,
                    caseinfo.getPetInfo(),
                    caseinfo.getCaseSymptom(),
                    caseCheck,
                    caseinfo.getCaseDiagnosis(),
                    caseMedicines,
                    caseinfo.getCaseTreat(),
                    caseinfo.getCaseSymptomPic()==null?null:caseinfo.getCaseSymptomPic().replace(" ",""),
                    caseinfo.getCaseSymptomVideo()==null?null:caseinfo.getCaseSymptomVideo().replace(" ",""),
                    caseinfo.getCaseCheckPic()==null?null:caseinfo.getCaseCheckPic().replace(" ",""),
                    caseinfo.getCaseCheckVideo()==null?null:caseinfo.getCaseCheckVideo().replace(" ",""),
                    caseinfo.getCaseDiagnosisPic()==null?null:caseinfo.getCaseDiagnosisPic().replace(" ",""),
                    caseinfo.getCaseDiagnosisVideo()==null?null:caseinfo.getCaseDiagnosisVideo().replace(" ",""),
                    caseinfo.getCaseTreatPic()==null?null:caseinfo.getCaseTreatPic().replace(" ",""),
                    caseinfo.getCaseTreatVideo()==null?null:caseinfo.getCaseTreatVideo().replace(" ",""),
                    caseinfo.getDefault1()==null? null :caseinfo.getDefault1().replace(" ",""),
                    caseinfo.getDefault2()==null?null:caseinfo.getDefault2().replace(" ",""),
                    caseinfo.getDefault3()==null?null:caseinfo.getDefault3().replace(" ","")
            );
            int code=caseMapper.updateByPrimaryKeyWithBLOBs(convertToCase);
            log.info("update的code是"+String.valueOf(code));
            return caseMapper.selectACaseById(caseId);
        }
        return null;


    }

    public boolean validateUrl(String urlstr){
        if(urlstr==null) return true;
        else{
            //先拆分，因为可能由多个地址
            String[] urls=urlstr.replace(" ","").split("\\|");
            for(String url:urls){
                if(url.matches("^(http(s)?://)?[a-zA-Z0-9-]+(\\.[a-zA-Z]{2,})+(/\\S*)?$"));
                else{
                    throw new CustomException(ResponseStatusEnum.BAD_REQUEST,url+"地址错误");

                }
            }
        }
        return true;
    }

    /**
     * 添加病例
     * @param caseinfo
     * @return
     */
    @Override
    public String addACase(CaseReceived caseinfo) {
        if(validateFields(caseinfo)){
            String newId='c'+getNumber(7);
            // 将时间字符串转换为 Date 类型,还有一些名称转id
            Date caseTime=validateDateAndToSQLDate(caseinfo.getCaseTime());
            String caseDiseases=diseaseNamesToDiseaseIds(caseinfo.getCaseDiseases());
            String caseCheck=labNamesToLabIds(caseinfo.getCaseCheck());
            String caseMedicines=medicineNamesToMedicineIds(caseinfo.getCaseMedicine());
            Case caseAdded=new Case(
                    newId,
                    caseDiseases,
                    caseTime,
                    caseinfo.getPetInfo(),
                    caseinfo.getCaseSymptom(),
                    caseCheck,
                    caseinfo.getCaseDiagnosis(),
                    caseMedicines,
                    caseinfo.getCaseTreat(),
                    caseinfo.getCaseSymptomPic()==null?null:caseinfo.getCaseSymptomPic().replace(" ",""),
                    caseinfo.getCaseSymptomVideo()==null?null:caseinfo.getCaseSymptomVideo().replace(" ",""),
                    caseinfo.getCaseCheckPic()==null?null:caseinfo.getCaseCheckPic().replace(" ",""),
                    caseinfo.getCaseCheckVideo()==null?null:caseinfo.getCaseCheckVideo().replace(" ",""),
                    caseinfo.getCaseDiagnosisPic()==null?null:caseinfo.getCaseDiagnosisPic().replace(" ",""),
                    caseinfo.getCaseDiagnosisVideo()==null?null:caseinfo.getCaseDiagnosisVideo().replace(" ",""),
                    caseinfo.getCaseTreatPic()==null?null:caseinfo.getCaseTreatPic().replace(" ",""),
                    caseinfo.getCaseTreatVideo()==null?null:caseinfo.getCaseTreatVideo().replace(" ",""),
                    caseinfo.getDefault1()==null? null :caseinfo.getDefault1().replace(" ",""),
                    caseinfo.getDefault2()==null?null:caseinfo.getDefault2().replace(" ",""),
                    caseinfo.getDefault3()==null?null:caseinfo.getDefault3().replace(" ","")

            );
            int code=caseMapper.insert(caseAdded);
            log.info("insert的code是"+String.valueOf(code));

            return newId;
        }
        return null;

    }

    /**
     * 验证接收到的caseinfo合法性：这里的合法性是指字段是否应该为null
     * @param caseinfo
     * @return
     */
    public boolean validateFields(CaseReceived caseinfo){
        List<Casefields> current=casefieldsMapper.selectAll();
        for(Casefields casefields:current){
            if(casefields.getChAttr()==null){
                //下划线命名转驼峰，因为case中的属性名称是驼峰命名，数据库中字段名（英文）是下划线
                String camelValue=convertToCamelCase(casefields.getEnAttr());
                if(caseinfo.getPropertyValue(camelValue)!=null&& !caseinfo.getPropertyValue(camelValue).toString().isEmpty())
                    throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"出现不存在的字段"+camelValue);
            }
        }
        return true;
    }

    public String diseaseNamesToDiseaseIds(String diseaseNames){
        //case_diseases换成disease_id
        String[] diseasesText=diseaseNames.replace(" ","").split("\\|");
        StringBuffer diseaseIds=new StringBuffer();
        boolean first=true;//是否是第一个，第一个前面不用|隔开
        for(String diseaseText:diseasesText){
            String diseaseId=diseaseMapper.selectDiseaseIdByName(diseaseText);
            if(diseaseId==null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,diseaseText+"不存在");
            if(first){
                diseaseIds.append(diseaseId);
                first=false;
            }
            else diseaseIds.append('|'+diseaseId);
        }
        return diseaseIds.toString();
    }

    public String labNamesToLabIds(String caseChecks){
        //case_check换成lab_id
        String[] labNames=caseChecks.replace(" ","").split("\\|");
        StringBuffer labIds=new StringBuffer();
        boolean first=true;
        for(String labName:labNames){
            String labId=labMapper.selectLabIdByName(labName);
            if(labId==null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,labName+"不存在");
            if(first){
                labIds.append(labId);
                first=false;
            }
            else labIds.append('|'+labId);
        }
        return labIds.toString();
    }

    public String medicineNamesToMedicineIds(String caseMedicines){
        //case_medicine换成medicine_id
        String[] medicineNames=caseMedicines.split("\\|");
        StringBuffer medicineIds=new StringBuffer();
        boolean first=true;
        for(String medicineName:medicineNames){
            String medicineId=medicineMapper.selectMedicineIdByName(medicineName);
//            log.info("药名"+medicineName);
            if(medicineId==null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,medicineName+"不存在");
            if(first){
                medicineIds.append(medicineId);
                first=false;
            }
            else medicineIds.append('|'+medicineId);
        }
        return medicineIds.toString();
    }

    public Date validateDateAndToSQLDate(String date){
        if(!isDate(date)) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,date+"不合法");
        return Date.valueOf(date);
    }

    /**
     * 批量删除病例，返回成功删除的id数组
     * @param caseIds
     * @return
     */
    @Override
    public List<String> deleteCases(String caseIds) {
        List<String> successIds=new ArrayList<>();
        for(String caseId:caseIds.replace(" ","").split("&")){
            if(!caseId.matches("c\\d{7}")) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,caseId+"不合法");
            int code=caseMapper.deleteByPrimaryKey(caseId);
            if(code!=1) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,caseId+"删除失败");
            else if(code==1){
                successIds.add(caseId);
            }
        }

        return successIds;
    }

}
